Skip to content

Changed: major NLP refactoring for flexibility and significantly improve performance #171

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Mar 6, 2025

Conversation

franckgaga
Copy link
Member

@franckgaga franckgaga commented Mar 5, 2025

First improvement

One big step further toward integration of DifferentiationInterface.jl

Related to #162

Second improvement

The splatting syntax of JuMP forces us to compute the Jacobians of the constraints as a combination of multiple gradients (concatenated as a Jacobian).

This means that the jacobian function of the AD tool (dense ForwardDiff.jl, for now) were called redundantly ng and neq times for a specific decision vector value (where ng and neq is the respective number of nonlinear inequality and equality constraints). This is wasteful. A caching mechanism was implemented to store the Jacobians of the constraints and reuse them when needed.

The performance improvement is about 5-10x faster now on NonLinMPC with NonLinModel. Note that it only applies when nonlinear constraints are present (i.e.: output or state constraint of nonlinear plant model, custom constraint and multiple shooting of nonlinear plant model)

FYI @baggepinnen and @1-Bart-1, will release it soon today or tomorrow.

edit : just tested this branch on the pendulum model. Now MultipleShooting is only 1.6x slower than the SingleShooting transcription (it was more than 5x times slower before), so it's plenty fast enough for real time! I'm really proud of this improvement 🍾🎉🍾 🎉. The additional gains will be using sparse differentiation with DifferentionInterface.jl.

@franckgaga franckgaga changed the title Changed: major NLP refactoring to reduce allocations Changed: major NLP refactoring for flexibility and to reduce allocations Mar 6, 2025
@codecov-commenter
Copy link

codecov-commenter commented Mar 6, 2025

Codecov Report

Attention: Patch coverage is 99.22179% with 2 lines in your changes missing coverage. Please review.

Project coverage is 98.85%. Comparing base (4269e90) to head (fc00d65).

Files with missing lines Patch % Lines
src/estimator/mhe/construct.jl 97.77% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #171      +/-   ##
==========================================
+ Coverage   98.81%   98.85%   +0.04%     
==========================================
  Files          25       25              
  Lines        4034     4118      +84     
==========================================
+ Hits         3986     4071      +85     
+ Misses         48       47       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…raints

The splatting syntax of `JuMP` forces use to compute the Jacobians of the inequality and equality constraints as a multiple gradients (concatenated in the Jacobian matrices).

This means that `jacobian!` function of the AD tools were called redundantly `ng` and `neq` times, for a specific decision vector value `Z̃`. This is wasteful. A caching mechanism was implemented to store the Jacobians of the constraints and reuse them when needed.

The performance improvement is about 5-10x faster now on `NonLinMPC` with `NonLinModel`.
@franckgaga franckgaga changed the title Changed: major NLP refactoring for flexibility and to reduce allocations Changed: major NLP refactoring for flexibility and significantly improve performance Mar 6, 2025
@franckgaga franckgaga merged commit ea1044b into main Mar 6, 2025
4 checks passed
@franckgaga franckgaga deleted the diff_interface branch March 6, 2025 23:04
@1-Bart-1
Copy link

1-Bart-1 commented Mar 7, 2025

Very cool, good work!!

@franckgaga
Copy link
Member Author

franckgaga commented Mar 7, 2025

@baggepinnen, did you noticed a performance regression between Julia 1.11 and 1.10? If I compare the nonlinear benchmarks of our paper on both version with ModelPredictiveControl v1.4.2, I get:

Julia lts channel (v1.10.8)

btime_NMPC_track_solver_IP = median(bm) = TrialEstimate(446.673 ms)
btime_NMPC_track_solver_IP2 = median(bm) = TrialEstimate(134.010 ms)
btime_NMPC_regul_solver_IP = median(bm) = TrialEstimate(387.229 ms)
btime_NMPC_regul_solver_IP2 = median(bm) = TrialEstimate(160.588 ms)
btime_EMPC_track_solver_IP = median(bm) = TrialEstimate(466.283 ms)
btime_EMPC_track_solver_IP2 = median(bm) = TrialEstimate(151.958 ms)
btime_EMPC_regul_solver_IP = median(bm) = TrialEstimate(464.341 ms)
btime_EMPC_regul_solver_IP2 = median(bm) = TrialEstimate(139.097 ms)
btime_SLMPC_track_solver_AS = median(bm) = TrialEstimate(6.457 ms)
btime_SLMPC_regul_solver_AS = median(bm) = TrialEstimate(5.967 ms)

Julia release channel (v1.11.3)

btime_NMPC_track_solver_IP = median(bm) = TrialEstimate(630.590 ms)
btime_NMPC_track_solver_IP2 = median(bm) = TrialEstimate(163.150 ms)
btime_NMPC_regul_solver_IP = median(bm) = TrialEstimate(560.399 ms)
btime_NMPC_regul_solver_IP2 = median(bm) = TrialEstimate(185.831 ms)
btime_EMPC_track_solver_IP = median(bm) = TrialEstimate(648.639 ms)
btime_EMPC_track_solver_IP2 = median(bm) = TrialEstimate(177.418 ms)
btime_EMPC_regul_solver_IP = median(bm) = TrialEstimate(691.486 ms)
btime_EMPC_regul_solver_IP2 = median(bm) = TrialEstimate(189.661 ms)
btime_SLMPC_track_solver_AS = median(bm) = TrialEstimate(7.322 ms)
btime_SLMPC_regul_solver_AS = median(bm) = TrialEstimate(7.413 ms)

Julia 1.11-nightly channel

btime_NMPC_track_solver_IP = median(bm) = TrialEstimate(626.744 ms)
btime_NMPC_track_solver_IP2 = median(bm) = TrialEstimate(156.591 ms)
btime_NMPC_regul_solver_IP = median(bm) = TrialEstimate(446.302 ms)
btime_NMPC_regul_solver_IP2 = median(bm) = TrialEstimate(147.617 ms)
btime_EMPC_track_solver_IP = median(bm) = TrialEstimate(654.216 ms)
btime_EMPC_track_solver_IP2 = median(bm) = TrialEstimate(171.278 ms)
btime_EMPC_regul_solver_IP = median(bm) = TrialEstimate(628.532 ms)
btime_EMPC_regul_solver_IP2 = median(bm) = TrialEstimate(181.976 ms)
btime_SLMPC_track_solver_AS = median(bm) = TrialEstimate(7.223 ms)
btime_SLMPC_regul_solver_AS = median(bm) = TrialEstimate(7.057 ms)

Should I raise an issue on julia's github?

@baggepinnen
Copy link
Member

baggepinnen commented Mar 8, 2025

I did not, if raising an issue, it would probably be good to narrow down slightly where the slowdown can have appeared? Are all installed dependencies the same in both cases? If not, the slowdown could be in one of them?

@franckgaga
Copy link
Member Author

franckgaga commented Mar 11, 2025

Ok good news ! I ran the benchmarks once more on the new release (v1.11.4), and now the differences with v1.10 is quite small, e.g. the first 2 tests gives (IP is Ipopt, IP2 is MadNLP):

btime_NMPC_track_solver_IP = median(bm) = TrialEstimate(457.770 ms)
btime_NMPC_track_solver_IP2 = median(bm) = TrialEstimate(128.249 ms)

I did not had the time to run them all but this is encouraging 🚀

edit: here's all the results. Some a a bit faster, some are a bit slower, but nothing problematic anymore IMO

btime_NMPC_track_solver_IP = median(bm) = TrialEstimate(457.770 ms)
btime_NMPC_track_solver_IP2 = median(bm) = TrialEstimate(128.249 ms)
btime_NMPC_regul_solver_IP = median(bm) = TrialEstimate(425.197 ms)
btime_NMPC_regul_solver_IP2 = median(bm) = TrialEstimate(143.778 ms)
btime_EMPC_track_solver_IP = median(bm) = TrialEstimate(457.981 ms)
btime_EMPC_track_solver_IP2 = median(bm) = TrialEstimate(137.837 ms)
btime_EMPC_regul_solver_IP = median(bm) = TrialEstimate(499.611 ms)
btime_EMPC_regul_solver_IP2 = median(bm) = TrialEstimate(147.623 ms)
btime_SLMPC_track_solver_AS = median(bm) = TrialEstimate(5.662 ms)
btime_SLMPC_regul_solver_AS = median(bm) = TrialEstimate(5.624 ms)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants